
/*
    C++的命名空间：
    1、创建名字是程序设计过程中一项最基本的活动，当一个项目很大时，它会不可避免地包含大量名字。c++允许我们对名字的产生和名字的可见性进行控制。
       在c语言中可以通过static关键字来使得名字只得在本编译单元内可见，在c++中我们将通过一种通过命名空间来控制对名字的访问。
    2、在C++中，名称（name）可以是符号常量、变量、宏、函数、结构、枚举、类和对象等等。
    3、std是c++标准命名空间，c++标准程序库中的所有标识符都被定义在std中，比如标准库中的类iostream、vector等都定义在该命名空间中，
       使用时要加上using声明(using namespace std)  或using指示(如std::cout)

    命名空间的定义:
    namespace 名称
    {
      //定义变量、函数、类型、对象
    }

    命名空间成员的访问:
    ·使用作用域操作符::
    ·空间名::成员
 */

#include <iostream>

using namespace std;

//声明一个命名空间，空间的名字叫做A
namespace A {
    int a = 10;

    void func() { cout << "这是命名空间A的函数" << endl; }
}

namespace B {
    int a = 20;
    void func() { cout << "这是命名空间B的函数" << endl; }
}

using namespace B;

//using namespace A;

//命名空间的嵌套定义
namespace C {
    int a = 30;
    namespace D {
        int a = 40;
    };
}

//可以将命名空间的声明和实现分开
#include "namespace.h"

//在cpp这边再实现
void CustomSpace::func1() {
    cout << "成功调用函数1" << endl;
}


int main() {

    //访问空间中的成员变量
    cout << "命名空间A中的变量a : " << A::a << endl;
    //因为上方已显式使用了 using namespace B，所以后续的变量a在不使用::的情况下，都会取B中的值。
    //同理，由于a同时存在于A和B当中，所以如果同时 using，那么编译器也不会知道我们到底想要用哪个，那么就会出现编译错误:Reference to 'a' is ambiguous
    cout << "命名空间B中的变量a : " << a << endl;
    a = 100;
    cout << "命名空间B中的变量a(修改后) : " << a << endl;
    //访问空间中的成员函数
    A::func();
    B::func();

    //命名空间只能在全局范围内定义。错误写法：
    // error: 'namespace' definition is not allowed here
//    namespace C{
//    }

    cout << "命名空间C中的变量a : " << C::a << endl;
    cout << "命名空间D中的变量a : " << C::D::a << endl;

    CustomSpace::func1();
    CustomSpace::func2(100);

    //命名空间别名(一般用于解决命名空间名称过长的情况)
    namespace other_name = CustomSpace;
    other_name::func2(1000);


    return 0;
}